<template>
  <div class="graph-page">
    <el-card>
      <template #header>
        <div class="card-header">
          <h3>知识图谱可视化</h3>
          <el-button type="primary" @click="loadGraph" :loading="loading">
            刷新图谱
          </el-button>
        </div>
      </template>
      
      <div v-if="!graphData" class="empty-state">
        <el-empty description="暂无图谱数据，请先进行知识抽取" />
      </div>
      
      <div v-else>
        <!-- 统计信息 -->
        <div class="graph-stats">
          <el-statistic title="总节点数" :value="graphData.nodes.length" />
          <el-statistic title="总关系数" :value="graphData.edges.length" />
        </div>
        
        <!-- 节点类型统计 -->
        <div class="node-stats">
          <div class="stat-item" v-for="stat in nodeStats" :key="stat.type">
            <div class="stat-color" :style="{ backgroundColor: stat.color }"></div>
            <div class="stat-label">{{ stat.type }}</div>
            <div class="stat-count">({{ stat.count }})</div>
          </div>
        </div>
        
        <div ref="chartRef" class="graph-container"></div>
      </div>
    </el-card>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, nextTick } from 'vue'
import { ElMessage } from 'element-plus'
import { graphAPI } from '../api'
import * as echarts from 'echarts'

const loading = ref(false)
const graphData = ref(null)
const chartRef = ref(null)
let chartInstance = null

// 节点类型颜色映射（与后端标准实体类型对应）
const categoryColors = {
  '设备名': '#409EFF',      // 蓝色
  '故障状态': '#E6A23C',    // 橙色
  '性能表征': '#67C23A',    // 绿色
  '故障原因': '#F56C6C',    // 红色
  '解决办法': '#909399'     // 灰色
}

// 关系类型的颜色映射
const relationColors = {
  '发生故障': '#409EFF',
  '表现': '#67C23A',
  '由原因引起': '#F56C6C',
  '导致': '#E6A23C',
  '通过办法解决': '#909399'
}

// 计算节点统计信息
const nodeStats = computed(() => {
  if (!graphData.value || !graphData.value.nodes) return []
  
  const stats = {}
  graphData.value.nodes.forEach(node => {
    const type = node.category || '未分类'
    if (!stats[type]) {
      stats[type] = {
        type: type,
        count: 0,
        color: categoryColors[type] || '#999'
      }
    }
    stats[type].count++
  })
  
  return Object.values(stats)
})

const loadGraph = async () => {
  loading.value = true
  try {
    const res = await graphAPI.getKnowledgeGraph()
    if (res.success) {
      graphData.value = res.graph
      await nextTick()
      renderGraph()
    } else {
      ElMessage.error('加载图谱失败')
    }
  } catch (error) {
    ElMessage.error(error.response?.data?.message || '加载图谱失败')
  } finally {
    loading.value = false
  }
}

const renderGraph = () => {
  if (!chartRef.value || !graphData.value) return
  
  // 数据验证
  if (!graphData.value.nodes || !Array.isArray(graphData.value.nodes)) {
    console.error('节点数据格式错误')
    return
  }
  
  if (!graphData.value.edges || !Array.isArray(graphData.value.edges)) {
    console.error('边数据格式错误')
    return
  }
  
  // 销毁旧实例
  if (chartInstance) {
    chartInstance.dispose()
  }
  
  // 创建新实例
  chartInstance = echarts.init(chartRef.value)
  
  // 处理节点数据
  const nodes = graphData.value.nodes.map(node => ({
    id: node.id || node.label,
    name: node.label || node.id,
    category: node.category || '未分类',
    symbolSize: 50,
    itemStyle: {
      color: categoryColors[node.category] || '#909399'
    },
    label: {
      show: true
    }
  }))
  
  // 处理边数据 - 添加箭头显示方向和关系标签
  const edges = graphData.value.edges.map(edge => ({
    source: edge.source,
    target: edge.target,
    value: edge.label,  // 关系名称
    // 添加箭头符号，显示明确的方向性
    symbol: ['none', 'arrow'],  // 起点无符号，终点是箭头
    symbolSize: [0, 15],  // 箭头大小
    lineStyle: {
      curveness: 0.2,
      width: 2,
      color: '#999',
      type: 'solid'
    },
    // 确保每条边都显示标签
    label: {
      show: true,
      formatter: edge.label
    }
  }))
  
  // 生成类别
  const categories = Object.keys(categoryColors).map(name => ({
    name,
    itemStyle: {
      color: categoryColors[name]
    }
  }))
  
  const option = {
    title: {
      text: '知识图谱可视化',
      left: 'center',
      textStyle: {
        fontSize: 20,
        fontWeight: 'bold'
      }
    },
    tooltip: {
      formatter: (params) => {
        if (params.dataType === 'node') {
          return `<b>${params.data.category}</b><br/>${params.data.name}`
        } else if (params.dataType === 'edge') {
          return `<b>${params.data.label?.formatter || params.data.label}</b><br/>${params.data.source} → ${params.data.target}`
        }
      }
    },
    legend: [
      {
        data: categories.map(c => c.name),
        orient: 'vertical',
        left: 'left',
        top: '12%',
        textStyle: {
          fontSize: 13
        },
        formatter: (name) => name
      }
    ],
    series: [{
      type: 'graph',
      layout: 'force',
      data: nodes,
      links: edges,
      categories: categories,
      roam: true,
      draggable: true,
      // 全局边设置
      edgeSymbol: ['none', 'arrow'],  // 显示箭头方向
      edgeSymbolSize: [0, 15],
      // 节点标签配置
      label: {
        show: true,
        position: 'right',
        formatter: '{b}',
        fontSize: 12,
        fontWeight: '500',
        color: '#303133'
      },
      // 边标签配置 - 简洁显示关系文字（始终显示）
      edgeLabel: {
        show: true,
        fontSize: 12,
        formatter: (params) => {
          return params.data.value || params.value || ''
        },
        color: '#666',
        position: 'middle'
      },
      labelLayout: {
        hideOverlap: false  // 不隐藏重叠的标签，确保所有关系都显示
      },
      force: {
        repulsion: 200,  // 增加斥力，让节点分散
        edgeLength: [150, 250],  // 增加边长，让结构更清晰
        gravity: 0.03,
        layoutAnimation: true
      },
      emphasis: {
        focus: 'adjacency',
        lineStyle: {
          width: 4
        },
        label: {
          fontSize: 14,
          fontWeight: 'bold'
        },
        edgeLabel: {
          fontSize: 13,
          color: '#303133'
        }
      },
      lineStyle: {
        opacity: 0.9,
        curveness: 0.3  // 稍微弯曲，避免重叠
      }
    }]
  }
  
  chartInstance.setOption(option)
  
  // 响应式调整
  window.addEventListener('resize', () => {
    chartInstance?.resize()
  })
}

onMounted(() => {
  loadGraph()
})
</script>

<style scoped>
.graph-page {
  width: 100%;
  max-width: 100%;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.card-header h3 {
  margin: 0;
}

.empty-state {
  min-height: 400px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.graph-stats {
  display: flex;
  gap: 40px;
  margin-bottom: 15px;
  justify-content: center;
}

.node-stats {
  display: flex;
  gap: 20px;
  margin-bottom: 20px;
  justify-content: center;
  flex-wrap: wrap;
  padding: 12px;
  background: #f9f9f9;
  border-radius: 6px;
}

.stat-item {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  background: white;
  border-radius: 4px;
}

.stat-color {
  width: 16px;
  height: 16px;
  border-radius: 50%;
}

.stat-label {
  font-size: 13px;
  font-weight: 500;
  color: #303133;
}

.stat-count {
  font-size: 13px;
  color: #909399;
}

.graph-container {
  width: 100%;
  height: 700px;
  border: 1px solid #eee;
  border-radius: 4px;
}
</style>

